/*
** $身份: 嘞国.h $
** 全局状态
** 参见 炉啊.h中的版权声明
*
** 本人所用声母表: a啊 b哔 c西 d迪 e鹅 f弗 g哥 
* h喝 i艾 j鸡 k颗 l嘞 m摸 n恩
* o欧 p匹 q气 r日 s丝 t嚏 
* u由 v微 w屋 x斯 y医 z只
*
* 一些英文单词缩写,我的翻译大多来自;有道词典,谷歌翻译,百度.
* 一些术语实在不好翻译,所以就原封不动.
* 
* 一些特有的表示特有库的术语是无法翻译的 *
* 否则编译器不能识别不能通过,第一版汉化就行不通.
* 
*/


#ifndef 嘞国_喝
#define 嘞国_喝

#include "炉啊.h"

#include "嘞对象.h"
#include "嘞标签方法.h"
#include "嘞只入出.h"

/*
**有关垃圾回收对象的注意事项,
  炉啊 中的所有对象必须以某种方式保持可访问性,直到被释放,
  所以所有对象都只属于这些列表中的一个,
  使用 '共同标头' 的 '下一个' 字段作为链接,
**
** '所有垃圾回收': 所有未标记为结束的对象;
** '最终对象': 所有标记为结束的对象;
** '存在已完成': 所有对象都准备好了最后定稿;
** '固定垃圾回收': 不被收集的所有对象 (目前只有小串,比如保留字).
**
** 对于生成回收,其中一些列表具有生成标记,
  每个标记指向特定生成的列表中的第一个元素,
  这一生成会一直活到下一标记,
**
** '所有垃圾回收' -> '存活': 新对象;
** '存活' -> '老旧': 在一次回收中存活的对象;
** '老旧' -> '真的老旧': 在上次回收中变旧的对象;
** '真的老旧' -> NULL: 对象的旧周期超过一个.
**
** '最终对象' -> '最终对象存活': 标记为已完成的新对象;
** '最终对象存活' -> '最终对象老旧': 存活的   """";
** '最终对象老旧' -> '最终对象真的老旧': 仅老旧  """";
** '最终对象真的老旧' -> NULL: 真的老旧       """".
*/


/*
  此外，还有另一组控制灰色对象的列表。
**这些列表由字段 '垃圾回收列表' 链接。
  (所有可以变成灰色的对象都有这样一个字段。
  字段在所有对象中并不相同，但它总是有这个名称。)
  任何灰色对象都必须属于这些列表中的一个，
  这些列表中的所有对象都必须是灰色的:
**
** '灰色': 普通的灰色对象,仍然等待被访问.
** '灰色再次': 必须在原子阶段重新访问的对象.
**   这包括
**   - 黑色对象进入了写障碍;
**   - 在传播阶段的各种弱表种类;
**   - 所有线程.
** '弱': 要清除具有弱值的表;
** '短命': 条目为白色->白色的短命表;
** '全弱': 要清除具有弱键 与/或 弱值的表.
*/


/*
  关于 '恩西调用' ;
  炉啊 (一个 炉啊_国)中的每个线程都保存了一个计数,
  它可以在西栈中执行多少 '西调用',
  避免西栈溢出,
 
  这个计数是非常粗略的估计;
  它只考虑解释器内部的递归函数,
  由于非递归调用可以考虑使用固定数量(尽管未知)的堆栈空间,
**
** 计数分为两部分:
   低的部分是计数它自己;
   高的部分计数栈中非产出调用的数量,
** (它们在一起,所以我们可以用一条指令改变它们,)
**
** 因为调用外部C函数可能会使用未知的空间
   (如使用辅助库缓冲区的函数),
   对这些函数的调用会增加一个以上的计数
   (见 西栈西弗),
**
** 正确的计数排除了 炉啊 分配的 调用信息 结构的数量,
   作为一种 '潜在' 调用,
   因此,当 炉啊 调用一个函数(并 '消费' 一个 调用信息)时,
   它既不需要减量也不需要检查 '恩西调用',
   因为它对C栈的使用已经说明,
*/

/* 外部C函数使用的 'C栈槽' 的数量 */

#define 西栈西弗	10

/*
** c栈大小被划分为以下区域:
** - 大于 西栈错误: 正常 栈;
** - [西栈标记, 西栈错误]: 缓冲区指示栈溢出;
** - [西栈西弗, 西栈错误标记]: 错误处理区;
** - 在 西栈错误标记 下面: 缓冲区在溢出期间发出溢出信号;
** (因为计数器可以立即递减西栈西弗, 我们需要所谓的 '缓冲区' ,
*   至少有那个尺寸, 正确地检测从一个区域到下一个区域的变化.)
*/

#define 西栈错误	(8 * 西栈西弗)
#define 西栈标记	(西栈错误 - (西栈西弗 + 2))
#define 西栈错误标记	(西栈西弗 + 2)

/* 线程的 c-栈 的初始极限 */
#define 西栈线程	(2 * 西栈错误)

/* 如果该线程在栈中没有不可输出的调用，则为 真 */
#define 可产出(嘞)		(((嘞)->恩西调用 & 0xffff0000) == 0)

/* C调用的实数 */
#define 取西调用(嘞)	((嘞)->恩西调用 & 0xffff)

/* 增加不可产出调用的数量 */
#define 增不产数(嘞)	((嘞)->恩西调用 += 0x10000)

/* 减少不可产出调用的数量 */
#define 减不产数(嘞)	((嘞)->恩西调用 -= 0x10000)

/* 增加不可产出调用的数量并减少 恩西调用 的数量 */
#define 增斯西调用(嘞)	((嘞)->恩西调用 += 0x10000 - 西栈西弗)

/* 减少不可产出调用的数量并增加 恩西调用 */
#define 减斯西调用(嘞)	((嘞)->恩西调用 -= 0x10000 - 西栈西弗)

struct 炉啊_长跳;  /* 定义在 嘞做.c 内 */

/*
** 原子类型(相对于信号)去更好地确保 '炉啊_设置钩子' 是线程安全的
*/
#if !defined(嘞_信号嚏)
#include <signal.h>
#define 嘞_信号嚏	sig_atomic_t
#endif

/* 处理 嚏摸 调用和其他额外的栈空间 */
#define 额外_栈   5


#define 基本_栈_大小        (2*炉啊_最小栈)


/* 垃圾回收的种类 */
#define 垃圾回收种类_增量		0	/* 增量 垃圾回收 */
#define 垃圾回收种类_生成		1	/* 生成 垃圾回收 */

typedef struct 串表 {
  嚏串 **哈希;
  int 元素号码;  /* 元素的数量 */
  int 大小;
} 串表;

/*
** 关于一个调用的信息.
*/

typedef struct 调用信息 {
  丝嚏颗身份  函;  /* 栈内函数索引 */
  丝嚏颗身份  顶;  /* 这个函数的顶部 */
  struct 调用信息 *先前, *下一个;  /* 动态调用链接 */
  union {
    struct {  /* 仅适用于炉啊函数 */
      const 指令 *保存迪匹西;
      volatile 嘞_信号嚏 陷阱;
      int 下一个变参实参;  /* # 可变参数函数中的额外实参 */
    } 嘞;
    struct {  /* 仅适用于C函数 */
      炉啊_颗函数 颗;  /* 在产出的情况下继续 */
      ptrdiff_t 老旧_错函;
      炉啊_颗上下文 西嚏斯;  /* 上下文信息. 在产出的情况下 */
    } 西;
  } 由;
  union {
    int 函索引;  /* 已调用函数的索引 */
    int 产出号;  /* 产出的值数 */
    struct {  /* 关于传输值的信息 (为 调用/返回 钩子) */
      unsigned short 第一传输;  /* 第一个传输值的偏移量 */
      unsigned short 传输号;  /* 传输值的数目 */
    } 传输信息;
  } 由2;
  short 结果号;  /* 此函数的预期结果数 */
  unsigned short 调用状态;
} 调用信息;

/*
** 调用信息状态内的位
*/
#define 调信状态_原有允许钩子	(1<<0)	/* '允许钩子'原有的值  */
#define 调信状态_西		(1<<1)	/* 调用正在运行一个C函数 */
#define 调信状态_钩子	(1<<2)	/* 调用正在运行一个调试钩子 */
#define 调信状态_产出保护调用	(1<<3)	/* 调用是一个可产出的受保护调用 */
#define 调信状态_尾	(1<<4)	/* 调用是尾调用 */
#define 调信状态_钩子产出	(1<<5)	/* 最后钩子调用已产出 */
#define 调信状态_终结	(1<<6)  /* 调用正在运行一个终结器 */
#define 调信状态_传输	(1<<7)	/* '调信' 享有传输信息 */
#if defined(炉啊_兼容_小于_小等)
#define 调信状态_小于等于	(1<<8)  /* 使用 __小于 为 __小等 */
#endif

/* 活动函数是 炉啊函数 */
#define 是否炉啊(调信)	(!((调信)->调用状态 & 调信状态_西))

/* 调用正在运行 炉啊代码 (不是一个钩子) */
#define 是否炉啊代码(调信)	(!((调信)->调用状态 & (调信状态_西 | 调信状态_钩子)))

/* 假设这个 调信状态_原有允许钩子 有偏移 0 与这个 '微' 是严格 0/1 */
#define 设置原有允许钩子(丝嚏,微)	((丝嚏) = ((丝嚏) & ~调信状态_原有允许钩子) | (微))
#define 取原有允许钩子(丝嚏)	((丝嚏) & 调信状态_原有允许钩子)

/*
** '全局状态', 由处于此状态的所有线程共享
*/
typedef struct 全局_国 {
  炉啊_分配 弗重新分配;  /* 函数重新分配内存 */
  void *由迪;         /* 辅助数据到 '弗重新分配' */
  嘞_内存 到嚏啊嘞字节;  /* 当前分配的字节数 - 垃圾回收债务 */
  嘞_内存 垃圾回收债务;  /* 已分配的字节尚未被回收器补偿 */
  炉_内存 垃圾回收估计;  /* 正在使用的非垃圾内存的估计 */
  炉_内存 最后原子;  /* 参见 '嘞垃圾回收.c' 文件中的函数 '生成步骤'  */
  串表 串嚏;  /* 串哈希表 */
  嚏值 嘞_寄存;
  嚏值 零值;  /* 一个零值 */
  unsigned int 种子;  /* 哈希的随机化种子 */
  炉_字节 当前白色;
  炉_字节 垃圾回收状态;  /* 垃圾回收器状态 */
  炉_字节 垃圾回收种类;  /* 垃圾回收器运行的类型 */
  炉_字节 生成次要摸由嘞;  /* 控制次要的生成回收 */
  炉_字节 生成主要摸由嘞;  /* 控制主要的生成回收 */
  炉_字节 垃圾回收正在运行;  /* 如果垃圾回收器正在运行,则为真 */
  炉_字节 垃圾回收紧急;  /* 如果这是紧急回收器,则为真 */
  炉_字节 垃圾回收暂停;  /* 连续垃圾回收之间的暂停大小 */
  炉_字节 垃圾回收步摸由嘞;  /* 垃圾回收 "速度" */
  炉_字节 垃圾回收步大小;  /* (它的对数) 垃圾回收的粒度 */
  垃圾回收对象 *所有垃圾回收;  /* 所有可回收对象的列表 */
  垃圾回收对象 **清扫垃圾回收;  /* 列表中扫描的当前位置 */
  垃圾回收对象 *终结器对象;  /* 具有终结器的可回收对象列表 */
  垃圾回收对象 *灰色;  /* 灰色对象列表 */
  垃圾回收对象 *再次灰色;  /* 要以原子方式遍历的对象的列表 */
  垃圾回收对象 *弱;  /* 具有弱值的表的列表 */
  垃圾回收对象 *短命;  /* 短命表的列表 (弱键) */
  垃圾回收对象 *所有弱;  /* 所有弱表的列表 */
  垃圾回收对象 *成为弗恩只;  /* 要进行垃圾回收的用户数据列表 */
  垃圾回收对象 *固定垃圾回收;  /* 不回收的对象列表 */
  /* 生成回收器的字段 */
  垃圾回收对象 *存活;  /* 从一个垃圾回收周期中幸存下来的对象的开始 */
  垃圾回收对象 *老旧;  /* 旧对象的开始 */
  垃圾回收对象 *真正老旧;  /* 一个周期以上的旧对象 */
  垃圾回收对象 *终结器对象存活;  /* 带有终结器的存活对象列表 */
  垃圾回收对象 *终结器对象老旧;  /* 带有终结器的旧对象列表 */
  垃圾回收对象 *终结器对象真正老旧;  /* 带有终结器的真正旧对象的列表 */
  struct 炉啊_国 *线程与上值;  /* 具有开放上值的线程列表 */
  炉啊_西函数 恐慌;  /* 在不受保护的错误中被调用 */
  struct 炉啊_国 *主线程;
  嚏串 *内存错误消息;  /* 内存分配错误消息 */
  嚏串 *标签方法名[标签方法_恩];  /* 带有标签方法名称的数组 */
  struct 表 *摸嚏[炉啊_标签号];  /* 基本类型的元表 */
  嚏串 *串缓存[串缓存_恩][串缓存_摸];  /* 在应用程序接口中缓存串 */
  炉啊_警告函数 警告函数;  /* 警告函数 */
  void *由迪_警告;         /* 辅助数据到 '警告函数' */
  unsigned int C栈极限;  /* C栈的当前限制 */
} 全局_国;

/*
** '每个线程' 状态
*/

struct 炉啊_国 {
  共同标头;
  炉_字节 状态;
  炉_字节 允许钩子;
  unsigned short 调信号;  /*  "调信" 列表中的项目数量 */
  丝嚏颗身份 顶;  /* 栈中的第一个空闲槽 */
  全局_国 *嘞_哥;
  调用信息 *调信;  /* 调用当前函数的信息 */
  const 指令 *老旧程序计数;  /* 最后程序计数追踪 */
  丝嚏颗身份 栈_最后;  /* 栈中的最后一个空闲槽 */
  丝嚏颗身份 栈;  /* 栈基地址 */
  上值 *打开上值;  /* 此栈中打开上值的列表 */
  垃圾回收对象 *垃圾回收列表;
  struct 炉啊_国 *线程与上值;  /* 打开上值的线程列表 */
  struct 炉啊_长跳 *错误跳;  /* 当前错误恢复点 */
  调用信息 基础_调信;  /* 第一级的调用信息 (C 调用 炉啊) */
  volatile 炉啊_钩子 钩子;
  ptrdiff_t 错函;  /* 当前的错误处理函数 (栈索引) */
  嘞_无符号整型32 恩西调用;  /* 允许的嵌套C调用数 - '调信号' */
  int 栈大小;
  int 基础钩子计数;
  int 钩子计数;
  volatile 嘞_信号嚏 钩子口罩;
};

#define 哥(嘞)	(嘞->嘞_哥)

/*
** 所有可收集对象的联合 (仅用于转换)
*/

union 垃圾回收联合 {
  垃圾回收对象 垃圾回收;  /* 共同标头 */
  struct 嚏串 嚏丝;
  struct 由数据 由;
  union 闭包 西嘞;
  struct 表 喝;
  struct 原型 匹;
  struct 炉啊_国 嚏喝;  /* 线程 */
  struct 上值 上微;
};

#define 投_由(欧)	投(union 垃圾回收联合 *, (欧))

/* 将垃圾回收对象转换为特定值的宏 */
#define 垃圾回收对象到嚏丝(欧)  \
	检查_表达式(不变体((欧)->嚏嚏) == 炉啊_嚏串, &((投_由(欧))->嚏丝))
#define 垃圾回收对象到由(欧)  检查_表达式((欧)->嚏嚏 == 炉啊_微用户数据, &((投_由(欧))->由))
#define 垃圾回收对象到嘞西嘞(欧)  检查_表达式((欧)->嚏嚏 == 炉啊_微嘞西嘞, &((投_由(欧))->西嘞.嘞))
#define 垃圾回收对象到西西嘞(欧)  检查_表达式((欧)->嚏嚏 == 炉啊_微西西嘞, &((投_由(欧))->西嘞.西))
#define 垃圾回收对象到西嘞(欧)  \
	检查_表达式(不变体((欧)->嚏嚏) == 炉啊_嚏函数, &((投_由(欧))->西嘞))
#define 垃圾回收对象到嚏(欧)  检查_表达式((欧)->嚏嚏 == 炉啊_微表, &((投_由(欧))->喝))
#define 垃圾回收对象到匹(欧)  检查_表达式((欧)->嚏嚏 == 炉啊_微原型, &((投_由(欧))->匹))
#define 垃圾回收对象到嚏喝(欧)  检查_表达式((欧)->嚏嚏 == 炉啊_微线程, &((投_由(欧))->嚏喝))
#define 垃圾回收对象到上微(欧)	检查_表达式((欧)->嚏嚏 == 炉啊_微上值, &((投_由(欧))->上微))

/*
** 宏将 炉啊 对象转换为 垃圾回收对象
** (对 '嚏嚏' 的访问试图确保 '微' 实际上是一个 炉啊 对象 .)
*/

#define 对象到垃圾回收对象(微)	检查_表达式((微)->嚏嚏 >= 炉啊_嚏串, &(投_由(微)->垃圾回收))


/* 实际分配的总字节数 */
#define 取总字节(哥)	投(炉_内存, (哥)->总字节 + (哥)->垃圾回收债务)

炉啊艾_函 void 炉啊鹅_设置债务 (全局_国 *哥, 嘞_内存 债务);
炉啊艾_函 void 炉啊鹅_自由线程 (炉啊_国 *嘞, 炉啊_国 *嘞1);
炉啊艾_函 调用信息 *炉啊鹅_扩展调信 (炉啊_国 *嘞);
炉啊艾_函 void 炉啊鹅_自由调信 (炉啊_国 *嘞);
炉啊艾_函 void 炉啊鹅_心理医生调信 (炉啊_国 *嘞);
炉啊艾_函 void 炉啊鹅_回车西调用 (炉啊_国 *嘞);
炉啊艾_函 void 炉啊鹅_警告 (炉啊_国 *嘞, const char *消息, int 去继续);
炉啊艾_函 void 炉啊鹅_警告错误 (炉啊_国 *嘞, const char *哪里);


#define 炉啊鹅_退出西调用(嘞)	((嘞)->恩西调用++)

#endif